package analiseSintatica.Regras.Tipos;

import java.util.LinkedList;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.Tipos.TipoSemantico;
import analiseSemantica.Tipos.TiposSemanticos;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;

/**
 *
 * @author Ivo Romário
 */

public class RegraTipo  extends Regra{



    protected static Regra instancia;

    protected String estrutura = "<tipo_primitivo> |  identificador | void";

    
    /**
     * Construtor privado necessario ao singleton
     */
    private RegraTipo() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraTipo getInstance() {
        if (instancia == null) {
            instancia = new RegraTipo();
        }
        return (RegraTipo) instancia;
    }

    
    @Override
    public TiposSemanticos analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

    	TiposSemanticos retorno;
    	if(listaContem(RegraTipoPrimitivo.getInstance().getPrimeiro(), listaTokens.getFirst())){
    		retorno = RegraTipoPrimitivo.getInstance().analisar(listaTokens);
         }else if(listaTokens.getFirst().getToken().equals("void")){
        	 LinkToken token = listaTokens.getFirst();
        	 TipoSemantico tipo = new TipoSemantico(token.getToken(), listaTokens.getFirst().getLinha());
             retorno = new TiposSemanticos();
             retorno.addTipos(tipo);
        	 reconheceToken(listaTokens, "void", estrutura);
         }else{
             ErroSintaticoException e = new ErroSintaticoException();
             e.addErros("Tipo esperado antes do token "+listaTokens.getFirst().getLexema(), estrutura, listaTokens.getFirst().getLinha());
             throw e;
         }
         
         return retorno;
    }

    @Override
    protected void setPrimeiro() {
        this.primeiro = RegraTipoPrimitivo.getInstance().getPrimeiro();
        this.primeiro = getUniao(primeiro, "void");
    }
}

